﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LiquidTrading.RapidAdditionHelper;
using LiquidTrading.RapidAdditionHelper.Clients;
using LiquidTrading.RapidAdditionHelper.Credentials;
using LiquidTrading.RapidAdditionHelper.Storage.LiquidView;
using System.IO;
using RapidAddition.FIXEngine;
using SterlingDropCopyConsole.Properties;
using System.Threading;

namespace SterlingDropCopyConsole
{
    class Program
    {
        static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("StartDropCopyClient");

                TimeSpan exitTime = Settings.Default.ExitTime;

                if (exitTime <= DateTime.Now.TimeOfDay)
                {
                    m_ExitTimer = new Timer(new TimerCallback(Shutdown), null, (long)TimeSpan.FromHours(24).Subtract(DateTime.Now.TimeOfDay).Add(exitTime).TotalMilliseconds, Timeout.Infinite);

                }
                else
                {
                    m_ExitTimer = new Timer(new TimerCallback(Shutdown), null, (long)Settings.Default.ExitTime.Subtract(DateTime.Now.TimeOfDay).TotalMilliseconds, Timeout.Infinite);
                }
                
                return StartDropCopyClient();
            }
            else if (args.Length == 2 && args[0] == "-f")
            {
                if (System.IO.File.Exists(args[1]))
                {
                    Console.WriteLine("StartFileBasedClient - Loading file: " + args[1]);
                    StartFileBasedClient(args[1]);
                }
                else
                {
                    Console.WriteLine("StartFileBasedClient - Cannot access file: " + args[1]);
                    Console.WriteLine("Exiting...");
                    System.Threading.Thread.Sleep(5000);
                }
            }     
            return 0;
        }

        public static string LOGFILE = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".txt";
        static int MAXRESTARTS = 5;

        static int m_RestartCounter;
        static bool m_ConsoleContinue;
        static Timer m_ExitTimer;
        static SterlingDropCopy m_FIXClient;

        static void Shutdown(object obj)
        {
            m_ConsoleContinue = false;
            Console.WriteLine("Time to exit Application");
            m_FIXClient.FIXSession.LogOff("Exiting Application");
            Log("Exiting SterlingDropCopyClient as reached ExitTime: " + Settings.Default.ExitTime);   
        }


        static void StartFileBasedClient(string filename)
        {
            TesterFileRepo creds = new TesterFileRepo("SterlingDropCopyLive", "FIX.4.2", ".\\Repo");

            SterlingStorage store = new SterlingStorage(creds.Id);
            
            using (SterlingDropCopy fixClient = new SterlingDropCopy(creds, store))
            {
                using (StreamReader reader = File.OpenText(filename))
                {
                    String message;
                    CFIXMessage fix;
                    while ((message = reader.ReadLine()) != null)
                    {
                        fix = new CFIXMessage(fixClient.FIXDataDictionary, message, true);

                        if (fix.Version == "FIX.4.2" && fix.MsgType == "8")
                            store.ProcessExecutionReportFIX42(fixClient.FIXDataDictionary, fix);
                    }
                }
            }
            
            creds = new TesterFileRepo("SterlingDropCopyLive", "FIX.5.0", ".\\Repo.FIX.5.0");

            store = new SterlingStorage(creds.Id);

            using (SterlingDropCopy fixClient = new SterlingDropCopy(creds, store))
            {
                using (StreamReader reader = File.OpenText(filename))
                {
                    String message;
                    CFIXMessage fix;
                    while ((message = reader.ReadLine()) != null)
                    {
                        fix = new CFIXMessage(fixClient.FIXDataDictionary, message, true);

                        if (fix.Version == "FIX.5.0" && fix.MsgType == "8")
                            store.ProcessExecutionReportFIX50(fixClient.FIXDataDictionary, fix);
                        else if (fix.Version == "FIXT.1.1" && fix.MsgType == "8")
                        {
                            fix.Version = "FIX.5.0";
                            store.ProcessExecutionReportFIX50(fixClient.FIXDataDictionary, fix);
                        }
                    }
                }
            }

            Console.WriteLine("File Complete...");
            System.Threading.Thread.Sleep(5000);
        }

        static void Log(string format, params object[] args)
        {
            Log(String.Format(format, args));
        }

        static void Log(string message)
        {
            File.AppendAllText(LOGFILE, DateTime.Now + "\t" + message + "\r\n");
        }

        static int StartDropCopyClient()
        {
            ConsoleKeyInfo cki;

            RemoveOldLogs();
                        
            FileRepoFileLog creds = new FileRepoFileLog(
                Settings.Default.Id,
                Settings.Default.FIX_Version,
                Settings.Default.FIX_Sender, 
                Settings.Default.FIX_Target, 
                Settings.Default.FIX_Host, 
                Settings.Default.FIX_Port, 
                Settings.Default.FIX_Heartbeat, 
                Settings.Default.RepoDir, 
                Settings.Default.LogDir, 
                true);

            // create new log directory;
            System.IO.Directory.CreateDirectory(creds.LogLocation);
            

            //FileRepoDBLog creds = new FileRepoDBLog("SterlingDropCopyLive", "FIX.4.2", "LIQUID", "SFS", "10.33.4.20", 19144, 30, "localhost", "RAPIDADDITION", "sa", "LIQTRADE", ".\\Repo");

            LOGFILE = creds.LogLocation + "\\" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + ".txt";

            Log("Starting StartDropCopyClient " + creds.ToString());

            SterlingStorage store = new SterlingStorage(creds.Id);

            bool isLoggedIn = false;
            m_ConsoleContinue = true;
            m_RestartCounter = 0;

            while (m_ConsoleContinue)
            {
                try
                {
                    using (m_FIXClient = new SterlingDropCopy(creds, store))
                    {
                        m_FIXClient.Start();

                        while (m_ConsoleContinue)
                        {
                            if (Console.KeyAvailable)
                            {
                                cki = Console.ReadKey(true);
                                switch (cki.Key)
                                {
                                    case ConsoleKey.X:
                                        Log("User pressed X to exit the application");
                                        Console.WriteLine("Exiting Application");
                                        m_FIXClient.FIXSession.LogOff("Exiting Application");
                                        Log("Exiting SterlingDropCopyClient");
                                        m_ConsoleContinue = false;
                                        break;
                                    default:
                                        Console.WriteLine("Avaliable options: x - Exit Application");
                                        break;
                                }
                            }
                            else if (!isLoggedIn && m_FIXClient.FIXSession.State == EFIXSessionState.LoggedOn)
                            {
                                isLoggedIn = true;
                                Log("Connected and logged in");
                                if (m_RestartCounter > 0)
                                {
                                    Log("Resetting restart counter to 0");
                                    m_RestartCounter = 0;
                                }
                            }
                            else if (m_FIXClient.IsLoggedOut)
                            {
                                isLoggedIn = false;
                                Log("FIX session is not logged in");
                                if (++m_RestartCounter >= MAXRESTARTS)
                                {
                                    Log("Quiting SterlingDropCopyClient due to to many retries");
                                    m_ConsoleContinue = false;
                                    return -1;
                                }
                                else
                                {
                                    Log("Restart {0} of {1}", m_RestartCounter, MAXRESTARTS);
                                    break;
                                }
                            }
                            else
                            {
                                System.Threading.Thread.Sleep(1000);
                            }
                        }                        
                    }
                    m_FIXClient = null;
                }
                catch (Exception e)
                {
                    Log("Caught an exception Source({0}) Message({1})", e.Source, e.Message);
                    Log(e.StackTrace);

                    if (e.InnerException != null)
                    {
                        Log("With inner exception Source({0}) Message({1})", e.InnerException.Source, e.InnerException.Message);
                        Log(e.InnerException.StackTrace);
                    }
                    if (++m_RestartCounter >= MAXRESTARTS)
                    {
                        Log("Quiting SterlingDropCopyClient due to to many retries");
                        return -2;
                    }
                    else
                    {
                        Log("Restart {0} of {1}", m_RestartCounter, MAXRESTARTS);
                    }
                }
            }
            return 0;
        }

        /// <summary>
        /// Removes old logs!
        /// </summary>
        static void RemoveOldLogs()
        {
            if (!System.IO.Directory.Exists(Settings.Default.LogDir))
                return;

            foreach (System.IO.DirectoryInfo dir in new System.IO.DirectoryInfo(Settings.Default.LogDir).GetDirectories("*", System.IO.SearchOption.TopDirectoryOnly))
            {
                foreach (System.IO.FileInfo file in dir.GetFiles("*.txt", System.IO.SearchOption.TopDirectoryOnly))
                {
                    if (file.LastWriteTime < DateTime.Now.AddDays(-Settings.Default.DaysToKeepLogs))
                        file.Delete();
                }

                if (dir.GetFiles().Length == 0 && dir.GetDirectories().Length == 0)
                    dir.Delete();
            }
        }
    }
}
